/**
 * @file filter
 * @author liaoxuezhi@baidu.com
 */
/* eslint fecs-indent: [0, "space", 2, 2] */

import * as React from 'react';
import {
  PureComponent,
  PropTypes
} from 'react';
import {render} from '../../renderer';
import {Enhance as FormItem} from '../form-item';
import * as Sensor from '../../../widgets/visibility-sensor.jsx';
import * as cx from 'classnames';
import * as debounce from 'lodash/debounce';
import './module-settings.scss';
import * as Sortable from 'sortablejs';
import * as find from 'lodash/find';

@FormItem({
  type: 'module-settings'
})
export default class ModuleSettings extends PureComponent {
  static propTypes = {
    className: PropTypes.string,
    formMode: PropTypes.string,
    formHorizontal: PropTypes.object,
    inputClassName: PropTypes.string
  };

  static defaultProps = {
    value: '',
    options: [
        {
            label: '志愿项目',
            type: 'm_1',
            icon: __uri('./projects@2x.png')
        }
    ]
  };

  constructor(props) {
    super(props);

    this.changeValue = this.changeValue.bind(this);
    this.addRow = this.addRow.bind(this);
    this.rowRef = this.rowRef.bind(this);
    this.optionsRef = this.optionsRef.bind(this);
    this.close = this.close.bind(this);
    this.handleFormResolved = this.handleFormResolved.bind(this);
    this.groupName = Date.now();

    this.sort = null;
    this.rowSorts = {};

    this.state = {
        options: props.options
    };
  }

  componentWillReceiveProps(nextProps) {
    const props = this.props;
    const combo = this.context.combo;

    if (props.sourceFetching && !nextProps.sourceFetching && nextProps.sourceData) {
      const sourceData = nextProps.sourceData;
      let options = sourceData && sourceData.hasOwnProperty('options') ? sourceData.options : sourceData;

      this.setState({
        options
      }, () => sourceData.hasOwnProperty('value') && this.props.setValue(sourceData.value));
    } else if (props.options !== nextProps.options || props.sourceLocalData !== nextProps.sourceLocalData) {
      const sourceLocalData = nextProps.sourceLocalData;
      let options = sourceLocalData || nextProps.options || [];

      this.setState({
        options
      });
    }
  }

  changeValue(value) {
    this.props.setValue(value);
  }

  addRow() {
      let value = this.props.getValue();

      if (!Array.isArray(value)) {
          value = [[]];
      }

      if (value.length > 2) {
        return;
      }

      value.push([]);
      this.props.setValue(value.concat());
  }

  removeRow(index) {
    let value = this.props.getValue();

    if (!Array.isArray(value)) {
        value = [[]];
    } else {
        value = value.concat();
    }

    value.splice(index, 1);
    this.props.setValue(value);
  }

  addItem(rowIndex, colIndex, moduleIndex) {
    let value = this.props.getValue();

    if (!Array.isArray(value)) {
        value = [[]];
    } else {
        value = value.concat();
    }

    const option = this.state.options[moduleIndex];

    value[rowIndex].splice(colIndex, 0, {
        ...option,
        settings: {
            label: option.label,
            icon: option.icon
        }
    });
    this.props.setValue(value);
  }

  removeItem(rowIndex, colIndex) {
    let value = this.props.getValue().concat();
    value[rowIndex].splice(colIndex, 1);
    this.props.setValue(value);
  }

  moveItem(fromX, fromY, toX, toY) {
    let value = this.props.getValue().concat();
    const [item] = value[fromX].splice(fromY, 1);
    value[toX].splice(toY, 0, item);
    this.props.setValue(value);
  }

  buildSchema(option) {
    return {
        title: '模块`' +option.label+ '`设置',
        body: {
            type: 'basic-form',
            controls: option.settings.map(item => ({
                ...item,
                name: item.key
            })).filter(item => item.type)
        }
    };
  }

  close() {
    this.setState({
        activeRow: -1,
        activeCol: -1,
        activeOption: null,
        schema: null
    });
  }

  handleFormResolved(values) {
    let value = this.props.getValue();

    if (!Array.isArray(value)) {
        value = [[]];
    } else {
        value = value.concat();
    }

    const {
        activeRow: x,
        activeCol: y
    } = this.state;

    value[x][y].settings = values;
    this.props.setValue(value);
    this.close();
  }

  rowRef(rowIndex, row) {
    if (!row) {
        let sort = this.rowSorts[rowIndex];
        if (sort) {
            delete this.rowSorts[rowIndex];
            sort.destroy();
        }
        return;
    }

    const sort = new Sortable(row, {
        group: {
            name: this.groupName,
            put: function (to) {
                return to.el.children.length < 5;
            }
        },
        filter: 'a.btn',
        onFilter: e => {
            const item = e.item;

            if (Sortable.utils.is(e.target, "a.btn-delete")) {  // Click on remove button
                this.removeItem(item.getAttribute('data-row'), item.getAttribute('data-col'));
            } else if (Sortable.utils.is(e.target, "a.btn-settings")) {
                let x = rowIndex, y = parseInt(item.getAttribute('data-col'), 10);
                let value = this.props.getValue();

                if (value && value[x] && value[x][y]) {
                    const option = value[x][y];
                    const raw = find(this.state.options, item => item.key ==option.key);

                    this.setState({
                        activeRow: x,
                        activeCol: y,
                        activeOption: option,
                        schema: this.buildSchema(raw)
                    });
                }
            }
        },
        onEnd: e => {
            const item = e.item;
            const parent = item.parentNode;

            if (!Sortable.utils.is(parent, '.module__row')) {
                return;
            }

            if (e.oldIndex !== e.newIndex || parent.getAttribute('data-index') != rowIndex) {
                e.from.insertBefore(item, e.from.childNodes[e.oldIndex]);
                this.moveItem(rowIndex, e.oldIndex, parent.getAttribute('data-index'), e.newIndex);
            }
        },
        animation: 100
    });
    this.rowSorts[rowIndex] = sort;
  }

  optionsRef(options) {
    if (!options) {
        this.sort && this.sort.destroy();
        this.sort = null;
        return;
    }

    const sort = this.sort = new Sortable(options, {
        group: {
            name: this.groupName,
            pull: 'clone',
            put: false
        },
        sort: false,
        onEnd: e => {
            const item = e.item;
            const parent = item.parentNode;
            // parent.removeChild(item);

            if (Sortable.utils.is(parent, '.module__row')) {
                parent.removeChild(item);
                this.addItem(parent.getAttribute('data-index'), e.newIndex, e.oldIndex);
            }
        }
    });
  }

  renderSelections() {
    const {
        getValue,
        name,
        $path,
        disabled
    } = this.props;
    const {
        activeRow: x,
        activeCol: y,
        schema,
        activeOption
    } = this.state;
    let value = getValue();

    if (!Array.isArray(value)) {
        value = [[]];
    }

    return (
        <div>
            <fieldset className="fieldSet">
                <legend>启用模块</legend>
                <div className="module__container">
                    {value.map((items, i) => (
                        <div key={`row-${i}`} className="clearfix">
                            <div className="module__row hbox pull-left" data-index={i} ref={this.rowRef.bind(this, i)}>
                                {items.map((option, j) => (
                                    <div key={`item-${i}-${j}`} data-row={i} data-col={j} className="col text-center">
                                        <div className={cx('module__item', {
                                            'active': i == x && y == j
                                        })}>
                                            <div className="module__item__toolbal">
                                                <a className="btn-settings btn btn-default btn-xs rounded m-r-xs"><i className="fa fa-cog" /></a>
                                                <a className="btn-delete btn btn-default btn-xs rounded"><i className="fa fa-minus text-danger" /></a>
                                            </div>
                                            <div className="module__item__icon">
                                                <img src={option.settings && option.settings.icon || option.icon} />
                                            </div>
                                            <label>{option.settings && option.settings.label || option.label}</label>
                                        </div>
                                    </div>
                                ))}
                            </div>

                            <button
                                type="button"
                                disabled={i === 0}
                                onClick={this.removeRow.bind(this, i)}
                                title="删除当前行"
                                className="btn btn-default btn-sm rounded pull-left m-l m-t"
                            >
                                <i className="fa fa-minus text-danger" />
                            </button>
                        </div>
                    ))}

                    {value.length > 2 ? null : (
                        <button
                            type="button"
                            onClick={this.addRow}
                            title="新增一行"
                            className="btn btn-default btn-sm rounded"
                        >
                            <i className="fa fa-plus" />
                        </button>
                    )}
                </div>
            </fieldset>

            {schema ? render(`${$path}/form-dialog`, schema, {
                key: `${x}-${y}`,
                data: activeOption.settings,
                name: `${name}-settings`,
                onClose: this.close,
                onResolved: this.handleFormResolved,
                disabled
                }) : null}
        </div>
    );
  }

  renderOptions() {
    const {options} = this.state;

    return (
        <div>
            <fieldset className="fieldSet">
                <legend>可用模块</legend>
                <div className="module__container" ref={this.optionsRef}>
                    {options.map((option, key) => (
                        <div key={key} className="module__item">
                            <div className="module__item__icon">
                                <img src={option.icon} />
                            </div>
                            <label>{option.label}</label>
                        </div>
                    ))}
                </div>
            </fieldset>
        </div>
    );
  }


  render() {
    const {
      disabled,
      inputClassName,
      placeholder,
      ignoreAddress
    } = this.props;

    return (
        <div
            className={cx('module-settings-control m-t', inputClassName)}
        >
            <div className="row">
                <div className="col-sm-7">
                    {this.renderSelections()}
                </div>
                <div className="col-sm-5">
                    {this.renderOptions()}
                </div>
            </div>
        </div>
    );
  }
}
